
const Hook = require('./Hook.js')

class HookCodeFactory {
    setup(instance, options) {
        this.options = options  // 这里源码是通过 init 方法实现，这里直接挂载在 this 上
        instance._x = options.taps.map(o => o.fn)
    }

    create(options) {
        // 核心是创建一段可执行的代码体直接返回
        return new Function(
            this.args({after: '_callback'}),
            this.head() + this.content()
        )
    }

    args({after, before} = {}) {
        let allArgs = this.options.args
        if (before) allArgs = [before].concat(allArgs)
        if (after) allArgs = allArgs.concat(after)
        return allArgs.join(',') // ['name, 'age']  ==>  name,age
    }

    head() {
        return `"use strict";var _content;var _x = this._x;`
    }

    content() {
        let code = `var _counter = ${this.options.taps.length};var _done = (function(){_callback();});`
        for (let i = 0; i < this.options.taps.length; i++) {
            code += `var _fn${i} = _x[${i}];_fn${i}(${this.args()},(function(){if (--_counter === 0) _done();}));`
        }
        return code
    }
}

let factory = new HookCodeFactory()
class AsyncParallelHook extends Hook {
    constructor(args) {
        super(args)
    }

    compile(options) {
        factory.setup(this, options)
        return factory.create(options)
    }
}

module.exports = AsyncParallelHook
